package sha256util

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/pem"
	"errors"

	Log "github.com/cihub/seelog"
)

type Sha256Util struct{}

// RSA公钥私钥产生
func (su Sha256Util) GenRsaKey() (string, string, error) {
	// 生成私钥文件
	privateKey, err := rsa.GenerateKey(rand.Reader, 1024)
	if err != nil {
		panic(err)
	}

	derStream := x509.MarshalPKCS1PrivateKey(privateKey)
	block := &pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: derStream,
	}

	prvkey := string(pem.EncodeToMemory(block))
	publicKey := &privateKey.PublicKey
	derPkix, err := x509.MarshalPKIXPublicKey(publicKey)
	if err != nil {
		Log.Error("私钥创建异常:", err)
		return "", "", errors.New("私钥创建异常!")
	}

	block = &pem.Block{
		Type:  "PUBLIC KEY",
		Bytes: derPkix,
	}

	pubkey := string(pem.EncodeToMemory(block))

	return prvkey, pubkey, nil
}

// 签名
func (su Sha256Util) RsaSignWithSha256(data, keyBytes string) (string, error) {
	h := sha256.New()
	h.Write([]byte(data))
	hashed := h.Sum(nil)

	block, _ := pem.Decode([]byte(keyBytes))
	if block == nil {
		return "", errors.New("私钥错误!")
	}

	privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		Log.Error("私钥解析错误", err)
		return "", errors.New("私钥解析错误!")
	}

	signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed)
	if err != nil {
		Log.Error("签名错误:", err)
		return "", errors.New("签名错误!")
	}

	return string(signature), nil
}

// 验证
func (su Sha256Util) RsaVerySignWithSha256(data, signData, keyBytes string) (bool, error) {
	block, _ := pem.Decode([]byte(keyBytes))
	if block == nil {
		return false, errors.New("公钥错误!")
	}

	pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		Log.Error("私钥错误:", err)
		return false, errors.New("私钥错误!")
	}

	hashed := sha256.Sum256([]byte(data))
	err = rsa.VerifyPKCS1v15(pubKey.(*rsa.PublicKey), crypto.SHA256, hashed[:], []byte(signData))
	if err != nil {
		Log.Error("公钥解析错误", err)
		return false, errors.New("公钥解析错误!")
	}

	return true, nil
}

// 公钥加密
func (su Sha256Util) RsaEncrypt(data, keyBytes string) (string, error) {
	//解密pem格式的公钥
	block, _ := pem.Decode([]byte(keyBytes))
	if block == nil {
		return "", errors.New("公钥错误!")
	}

	// 解析公钥
	pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		Log.Error("公钥解析错误", err)
		return "", errors.New("公钥解析错误!")
	}

	// 类型断言
	pub := pubInterface.(*rsa.PublicKey)
	//加密
	ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, pub, []byte(data))
	if err != nil {
		Log.Error("加密错误", err)
		return "", errors.New("加密错误!")
	}

	return string(ciphertext), nil
}

// 私钥解密
func (su Sha256Util) RsaDecrypt(ciphertext, keyBytes string) (string, error) {
	//获取私钥
	block, _ := pem.Decode([]byte(keyBytes))
	if block == nil {
		return "", errors.New("私钥错误!")
	}

	//解析PKCS1格式的私钥
	priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		Log.Error("私钥解析错误", err)
		return "", err
	}

	// 解密
	data, err := rsa.DecryptPKCS1v15(rand.Reader, priv, []byte(ciphertext))
	if err != nil {
		Log.Error("解密错误", err)
		return "", err
	}

	return string(data), nil
}
